package org.aeon.colorfulplanebattle.view;

import org.aeon.colorfulplanebattle.constant.GameStateE;
import org.aeon.colorfulplanebattle.view.listener.GameKeyListener;
import org.aeon.colorfulplanebattle.view.components.PopUp;
import org.aeon.colorfulplanebattle.view.logic.TaskManage;
import org.aeon.colorfulplanebattle.view.panel.WelcomePage;

import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static org.aeon.colorfulplanebattle.constant.GameStateE.IN_PROGRESS;

/**
 * @author: MissingAeon
 * @date: 2024/1/10 10:48
 * @description:
 */
public class GameState {
    private final Map<String, Object> messageBus;   // 消息总线容器
    private GameStateE state;
    private GameUI gameUI;

    private GameState() {
        messageBus = new ConcurrentHashMap<>();
    }

    /**
     * 开始
     */
    public static void startUp() {
        try {
            SwingUtilities.invokeAndWait(() -> {
                GameState state = new GameState();
                state.gameUI = new GameUI(state);
                state.setState(GameStateE.INIT);
            });
        } catch (InterruptedException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private void init() {
        this.put("gameUI", gameUI);
        PopUp popUp = new PopUp(this, new WelcomePage(this));
        this.put("welcome", popUp);
        gameUI.setVisible(true);
        popUp.setVisible(true);
    }


    /**
     * 获取状态
     *
     * @return
     */
    public GameStateE getState() {
        return state;
    }

    /**
     * 状态设置
     *
     * @param state
     */
    public void setState(GameStateE state) {
        if (state == this.state) return;
        this.state = state;
        switch (state) {
            // 初始化
            case INIT -> init();
            // 新游戏
            case NEW -> {
                TaskManage.prepare(this);
                gameUI.repaint();
                GameKeyListener.gameListener().setMyPlane(this.get("myPlane"));
                reset();
                this.setState(IN_PROGRESS);
            }
            // 继续游戏
            case HEAVY_LOAD -> {
                return;
            }
            // 正在游戏
            case IN_PROGRESS -> {    // 关闭开始弹窗
                if (this.exist("welcome")) {
                    ((PopUp) this.get("welcome")).setVisible(false);
                }
                // 关闭总结
                if (this.exist("settlement"))
                    ((PopUp) this.get("settlement")).setVisible(false);
                // 添加键盘监听
                gameUI.addKeyListener(GameKeyListener.gameListener());
                // 开始任务
                TaskManage.startUp();
            }
            // 暂停
            case SUSPEND -> {
                return;
            }
            // 得分界面
            case SCORING -> {
                if (this.exist("settlement")) {
                    PopUp settlement = this.get("settlement");
                    settlement.setVisible(true);
                }
            }
            // 退出
            case FINISH -> close();
        }
    }

    /**
     * 重置
     * 每当当开始游戏时调用
     */
    private void reset() {
        ((Runnable) this.get("BattlefieldReset")).run();
        ((Runnable) this.get("BloodBarReset")).run();
        ((Runnable) this.get("ScoreboardReset")).run();
        ((Runnable) this.get("BottomPanelReset")).run();
        ((Runnable) this.get("ClockReset")).run();
        // ((Runnable) this.get("GameKeyListenerReset")).run();
        GameKeyListener.gameListener().reset();
    }

    public void close() {
        if (this.exist("welcome")) {
            ((JDialog) this.pop("welcome")).setVisible(false);
        }
        if (this.exist("settlement"))
            ((JDialog) this.pop("settlement")).dispose();
        if (gameUI != null)
            gameUI.dispose();
        System.exit(0);
    }

    /**
     * 获取消息值
     * 当无法转换时抛出错误
     *
     * @param key
     * @return 返回 value
     */
    public <E> E get(String key) {
        return (E) messageBus.get(key);
    }

    /**
     * 添加消息
     *
     * @param key
     * @param value
     * @return 如果被替换，返回之前的value，否则返回null
     */
    public Object put(String key, Object value) {
        if (value == null) {
            return pop(key);
        }
        return messageBus.put(key, value);
    }

    /**
     * 获取消息值并删除消息
     * 当无法转换时抛出错误
     *
     * @param key
     * @return 返回 value
     */
    public <E> E pop(String key) {
        E e = (E) messageBus.get(key);
        messageBus.remove(key);
        return e;
    }

    /**
     * 判断该密匙是否存在
     * 虽不保证内容是否为空
     * 但约定不会出现 put(key,null);
     *
     * @param key
     * @return
     */
    public boolean exist(String key) {
        return messageBus.containsKey(key);
    }
}
